//! 内存管理模块
//! 
//! 负责数据库的内存分配、页面管理和缓冲池

use crate::{Error, Result, config::DatabaseConfig};
use std::collections::{HashMap, VecDeque};
use std::sync::atomic::{AtomicUsize, Ordering};
use parking_lot::RwLock;

/// 内存管理器
#[derive(Debug)]
pub struct MemoryManager {
    /// 配置
    config: DatabaseConfig,
    /// 页面池
    page_pool: RwLock<PagePool>,
    /// 内存使用统计
    memory_usage: AtomicUsize,
}

impl MemoryManager {
    /// 创建新的内存管理器
    pub fn new(config: &DatabaseConfig) -> Result<Self> {
        let page_pool = PagePool::new(config.page_size, config.buffer_pool_size)?;
        
        Ok(Self {
            config: config.clone(),
            page_pool: RwLock::new(page_pool),
            memory_usage: AtomicUsize::new(0),
        })
    }
    
    /// 分配页面
    pub fn allocate_page(&self) -> Result<PageId> {
        let mut pool = self.page_pool.write();
        let page_id = pool.allocate_page()?;
        
        self.memory_usage.fetch_add(self.config.page_size, Ordering::Relaxed);
        
        tracing::debug!("分配页面: {:?}", page_id);
        Ok(page_id)
    }
    
    /// 释放页面
    pub fn deallocate_page(&self, page_id: PageId) -> Result<()> {
        let mut pool = self.page_pool.write();
        pool.deallocate_page(page_id)?;
        
        self.memory_usage.fetch_sub(self.config.page_size, Ordering::Relaxed);
        
        tracing::debug!("释放页面: {:?}", page_id);
        Ok(())
    }
    
    /// 获取页面数据
    pub fn get_page(&self, page_id: PageId) -> Result<Vec<u8>> {
        let pool = self.page_pool.read();
        pool.get_page_data(page_id)
    }
    
    /// 写入页面数据
    pub fn write_page(&self, page_id: PageId, data: Vec<u8>) -> Result<()> {
        let mut pool = self.page_pool.write();
        pool.write_page_data(page_id, data)
    }
    
    /// 获取内存使用量
    pub fn memory_usage(&self) -> usize {
        self.memory_usage.load(Ordering::Relaxed)
    }
    
    /// 获取内存使用率
    pub fn memory_usage_ratio(&self) -> f64 {
        self.memory_usage() as f64 / self.config.memory_limit as f64
    }
    
    /// 检查内存是否充足
    pub fn has_sufficient_memory(&self, required: usize) -> bool {
        self.memory_usage() + required <= self.config.memory_limit
    }
    
    /// 强制垃圾回收
    pub fn force_gc(&self) -> Result<usize> {
        let mut pool = self.page_pool.write();
        let freed_pages = pool.garbage_collect()?;
        
        let freed_memory = freed_pages * self.config.page_size;
        self.memory_usage.fetch_sub(freed_memory, Ordering::Relaxed);
        
        tracing::info!("垃圾回收完成，释放 {} 页面，{} 字节", freed_pages, freed_memory);
        Ok(freed_memory)
    }
}

/// 页面池
#[derive(Debug)]
struct PagePool {
    /// 页面大小
    page_size: usize,
    /// 最大页面数
    max_pages: usize,
    /// 页面存储
    pages: HashMap<PageId, Page>,
    /// 空闲页面队列
    free_pages: VecDeque<PageId>,
    /// 下一个页面ID
    next_page_id: u64,
}

impl PagePool {
    /// 创建新的页面池
    fn new(page_size: usize, buffer_pool_size: usize) -> Result<Self> {
        let max_pages = buffer_pool_size / page_size;
        
        if max_pages == 0 {
            return Err(Error::config("缓冲池大小太小"));
        }
        
        Ok(Self {
            page_size,
            max_pages,
            pages: HashMap::new(),
            free_pages: VecDeque::new(),
            next_page_id: 1,
        })
    }
    
    /// 分配页面
    fn allocate_page(&mut self) -> Result<PageId> {
        // 检查是否有空闲页面
        if let Some(page_id) = self.free_pages.pop_front() {
            return Ok(page_id);
        }
        
        // 检查是否达到最大页面数
        if self.pages.len() >= self.max_pages {
            return Err(Error::OutOfMemory);
        }
        
        // 创建新页面
        let page_id = PageId(self.next_page_id);
        self.next_page_id += 1;
        
        let page = Page::new(self.page_size);
        self.pages.insert(page_id, page);
        
        Ok(page_id)
    }
    
    /// 释放页面
    fn deallocate_page(&mut self, page_id: PageId) -> Result<()> {
        if !self.pages.contains_key(&page_id) {
            return Err(Error::storage("页面不存在"));
        }
        
        // 清空页面数据
        if let Some(page) = self.pages.get_mut(&page_id) {
            page.clear();
        }
        
        // 添加到空闲队列
        self.free_pages.push_back(page_id);
        
        Ok(())
    }
    
    /// 获取页面数据
    fn get_page_data(&self, page_id: PageId) -> Result<Vec<u8>> {
        let page = self.pages.get(&page_id)
            .ok_or_else(|| Error::storage("页面不存在"))?;
        
        Ok(page.data.clone())
    }
    
    /// 写入页面数据
    fn write_page_data(&mut self, page_id: PageId, data: Vec<u8>) -> Result<()> {
        let page = self.pages.get_mut(&page_id)
            .ok_or_else(|| Error::storage("页面不存在"))?;
        
        if data.len() > self.page_size {
            return Err(Error::storage("数据大小超过页面大小"));
        }
        
        page.data = data;
        page.dirty = true;
        
        Ok(())
    }
    
    /// 垃圾回收
    fn garbage_collect(&mut self) -> Result<usize> {
        let mut freed_count = 0;
        
        // 移除空闲页面
        while let Some(page_id) = self.free_pages.pop_front() {
            if self.pages.remove(&page_id).is_some() {
                freed_count += 1;
            }
        }
        
        Ok(freed_count)
    }
}

/// 页面ID
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PageId(u64);

impl PageId {
    /// 获取页面ID值
    pub fn value(&self) -> u64 {
        self.0
    }
}

/// 页面
#[derive(Debug)]
struct Page {
    /// 页面数据
    data: Vec<u8>,
    /// 是否脏页
    dirty: bool,
    /// 访问计数
    access_count: usize,
    /// 最后访问时间
    last_access: std::time::Instant,
}

impl Page {
    /// 创建新页面
    fn new(size: usize) -> Self {
        Self {
            data: vec![0; size],
            dirty: false,
            access_count: 0,
            last_access: std::time::Instant::now(),
        }
    }
    
    /// 清空页面
    fn clear(&mut self) {
        self.data.fill(0);
        self.dirty = false;
        self.access_count = 0;
        self.last_access = std::time::Instant::now();
    }
    
    /// 标记访问
    fn mark_access(&mut self) {
        self.access_count += 1;
        self.last_access = std::time::Instant::now();
    }
}

/// 内存统计信息
#[derive(Debug, Clone)]
pub struct MemoryStats {
    /// 总内存使用量
    pub total_memory: usize,
    /// 页面数量
    pub page_count: usize,
    /// 空闲页面数量
    pub free_page_count: usize,
    /// 内存使用率
    pub usage_ratio: f64,
}

impl MemoryManager {
    /// 获取内存统计信息
    pub fn get_stats(&self) -> MemoryStats {
        let pool = self.page_pool.read();
        
        MemoryStats {
            total_memory: self.memory_usage(),
            page_count: pool.pages.len(),
            free_page_count: pool.free_pages.len(),
            usage_ratio: self.memory_usage_ratio(),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    
    #[test]
    fn test_memory_manager_creation() {
        let config = DatabaseConfig::default();
        let memory_manager = MemoryManager::new(&config).unwrap();
        
        assert_eq!(memory_manager.memory_usage(), 0);
        assert!(memory_manager.memory_usage_ratio() < 0.01);
    }
    
    #[test]
    fn test_page_allocation() {
        let config = DatabaseConfig::default();
        let memory_manager = MemoryManager::new(&config).unwrap();
        
        let page_id = memory_manager.allocate_page().unwrap();
        assert!(page_id.value() > 0);
        assert_eq!(memory_manager.memory_usage(), config.page_size);
    }
    
    #[test]
    fn test_page_deallocation() {
        let config = DatabaseConfig::default();
        let memory_manager = MemoryManager::new(&config).unwrap();
        
        let page_id = memory_manager.allocate_page().unwrap();
        memory_manager.deallocate_page(page_id).unwrap();
        
        assert_eq!(memory_manager.memory_usage(), 0);
    }
    
    #[test]
    fn test_page_data_operations() {
        let config = DatabaseConfig::default();
        let memory_manager = MemoryManager::new(&config).unwrap();
        
        let page_id = memory_manager.allocate_page().unwrap();
        let test_data = vec![1, 2, 3, 4, 5];
        
        memory_manager.write_page(page_id, test_data.clone()).unwrap();
        let read_data = memory_manager.get_page(page_id).unwrap();
        
        assert_eq!(read_data[0..5], test_data[..]);
    }
    
    #[test]
    fn test_memory_stats() {
        let config = DatabaseConfig::default();
        let memory_manager = MemoryManager::new(&config).unwrap();
        
        let _page_id = memory_manager.allocate_page().unwrap();
        let stats = memory_manager.get_stats();
        
        assert_eq!(stats.page_count, 1);
        assert_eq!(stats.free_page_count, 0);
        assert!(stats.usage_ratio > 0.0);
    }
}
